# -*- coding: utf-8 -*-
#
# The Philatelist program is a fork of the OpenNumismat program
# Copyright (c) 2011 - 2024 Vitaly Ignatov (OpenNumismat) <opennumismat@gmail.com>
# Copyright (c) 2021 - 2024 Victor Nabatov (Philatelist) <nabatov.victor@gmail.com>
#
import os.path

from PySide6.QtCore import Qt, QObject, QMargins, Signal as pyqtSignal
from PySide6.QtSql import QSqlQuery
from PySide6.QtWidgets import QBoxLayout, QCheckBox, QHBoxLayout, QSizePolicy, QVBoxLayout, QWidget

import Philatelist
from Philatelist.Collection.CollectionFields import ImagesFields, TraitsImagesFields, FieldTypes as Type
from Philatelist.ImageEditor import ImageProxy, ImageScrollLabel
from Philatelist.Settings import Settings
from Philatelist.StampEditor.ImageLabel import ImageLabel


class ImageView(QWidget):

    prevRecordEvent = pyqtSignal(QObject)
    nextRecordEvent = pyqtSignal(QObject)

    def __init__(self, direction, parent=None):
        super().__init__(parent)
        self.currentIndex = None
        if direction == QBoxLayout.LeftToRight:
            layout = self.__createHorizontalLayout()
        else:
            layout = self.__createVerticalLayout()

        self.setLayout(layout)

    def __createVerticalLayout(self):
        layout = QVBoxLayout()
        self.imageLayout = QVBoxLayout()
        self.imageLayout.setContentsMargins(QMargins())
        layout.addWidget(self.__layoutToWidget(self.imageLayout))
        self.buttonLayout = QHBoxLayout()
        self.buttonLayout.setAlignment(Qt.AlignCenter | Qt.AlignBottom)
        widget = self.__layoutToWidget(self.buttonLayout)
        widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        layout.addWidget(widget)
        return layout

    def __createHorizontalLayout(self):
        layout = QHBoxLayout()
        self.buttonLayout = QVBoxLayout()
        self.buttonLayout.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
        widget = self.__layoutToWidget(self.buttonLayout)
        widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        layout.addWidget(widget)

        self.imageLayout = QHBoxLayout()
        self.imageLayout.setContentsMargins(QMargins())
        layout.addWidget(self.__layoutToWidget(self.imageLayout))
        return layout

    def setModel(self, model):
        self.model = model
        # stamp image, reverse image, variety image
        self.imagesFields = []
        # grid image, honecomb image, raster image and watermark image
        self.traitsFields = []
        for field in self.model.fields.userFields:
            if field.type == Type.Image:
                self.imagesFields.append(field)
                if field.name in TraitsImagesFields:
                    trait_field = field.name.replace('_image', '')
                    index = self.model.fieldIndex(trait_field)
                    self.traitsFields.append(self.model.fields.userFields[index])

        # By default show stamp, glue and trait images
        self.showedCount = Settings()['images_by_default']
        # List of checkBoxes to enable or disable the visibility of images
        self.imageButtons = []
        for field in self.imagesFields:
            button = QCheckBox(self)
            button.setToolTip(field.title)
            button.setDisabled(True)
            button.stateChanged.connect(self.buttonClicked)
            self.imageButtons.append(button)
            self.buttonLayout.addWidget(button)

    def clear(self):
        while self.imageLayout.count():
            item = self.imageLayout.takeAt(0)
            w = item.widget()
            self.imageLayout.removeItem(item)
            w.deleteLater()

    def buttonClicked(self, _state):
        self.clear()
        current = self.currentIndex
        self.showedCount = 0
        for i, field in enumerate(self.imagesFields):
            if self.imageButtons[i].isChecked():
                # Show images related to the current stamp according to checked boxes
                imageName = self.getImageFileName(current, field)
                if imageName:
                    self.getImageAndSetTooltip(field, current, imageName)
                    self.showedCount += 1

    def rowChangedEvent(self, current):
        self.currentIndex = current
        self.clear()
        for i, field in enumerate(self.imagesFields):
            self.imageButtons[i].stateChanged.disconnect(self.buttonClicked)
            self.imageButtons[i].setCheckState(Qt.Unchecked)
            self.imageButtons[i].setDisabled(True)
            self.imageButtons[i].setStyleSheet("background-color: #dddddd")
            # Show images related to the current stamp
            imageName = self.getImageFileName(current, field)
            if imageName:
                if self.imageLayout.count() < self.showedCount:
                    self.getImageAndSetTooltip(field, current, imageName)
                    self.imageButtons[i].setCheckState(Qt.Checked)

                self.imageButtons[i].setDisabled(False)
                self.imageButtons[i].setStyleSheet("background-color: #9c9c9c")

            self.imageButtons[i].stateChanged.connect(self.buttonClicked)

    def imageEdited(self, image):
        record = self.model.record(self.currentIndex.row())
        record.setValue(image.field, image.image)
        self.model.setRecord(self.currentIndex.row(), record)
        self.model.submitAll()
        for i in range(self.imageLayout.count()):
            image_label = self.imageLayout.itemAt(i).widget()
            if image_label.field == image.field:
                image_label._setImage(image.image)

    def getImageProxy(self):
        imageProxy = ImageProxy(self)
        imageProxy.prevRecordEvent.connect(self.prevRecordEvent)
        imageProxy.nextRecordEvent.connect(self.nextRecordEvent)
        for field in self.imagesFields:
            index = self.model.index(self.currentIndex.row(), field.id)
            img_file = self.getImageFileName(index, field)
            if img_file:
                image = ImageScrollLabel(field.name, field.title, self)
                image.loadFromFile(img_file)
                image.imageEdited.connect(self.imageEdited)
                imageProxy.append(image)

        return imageProxy

    def __layoutToWidget(self, layout):
        widget = QWidget(self)
        widget.setLayout(layout)
        return widget

    def getImageFileName(self, current, field):
        index: object = self.model.index(current.row(), field.id)
        image_file = index.data(Qt.ItemDataRole.UserRole)
        if image_file:
            if field.name in ImagesFields:
                return os.path.join(Philatelist.IMAGES_PATH, image_file)
            else:
                return os.path.join(Philatelist.RESOURCES_PATH, image_file)

        return None

    def getImageAndSetTooltip(self, field, current, image_file):
        title = None
        image = ImageLabel(field.name, None, self)
        stamp_Id = self.model.record(current.row()).value('id')
        if field.name in ImagesFields:
            image.loadFromFile(image_file)
            if field.name in ('stamp_image', 'reverse_image'):
                title = self.model.getImageTitle(stamp_Id)
            else:
                if field.name == 'variety_image':
                    field_name = field.name.replace('_image', '')
                else:
                    field_name = field.name + '_title'

                title = self.model.record(current.row()).value(field_name)
        else:
            image.loadFromFile(image_file)
            table_name = "ref_%s" % field.name.replace('_image', '')
            sql = "SELECT value FROM %s WHERE path=?" % table_name
            query = QSqlQuery(sql, self.model.reference.db)
            query.addBindValue(image_file)
            query.exec_()
            if query.first():
                title = query.record().value(0)

        image.setToolTip(title)
        image.imageEdited.connect(self.imageEdited)
        self.imageLayout.addWidget(image)
